use std::io;
use std::io::Write;
use std::sync::Arc;
use std::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release, SeqCst};
use std::sync::atomic::{AtomicU8};
use std::thread::spawn;

static FLAG: AtomicU8 = AtomicU8::new(0);
struct AtomicStruct{
    a:AtomicU8,
    b:AtomicU8,
}
impl AtomicStruct{
    fn new()->Self{
        Self{
            a:AtomicU8::new(0),
            b:AtomicU8::new(0)
        }
    }
}


fn main() {
    let atomic_struct = Arc::new(AtomicStruct::new());
    let atomic_struct_clone = atomic_struct.clone();
    let atomic_struct_clone1 = atomic_struct.clone();
    spawn(move || {
        loop {
            if FLAG.load(SeqCst) & 1 > 0 {
                atomic_struct_clone.b.store(1,Relaxed);
                 print!("{}", atomic_struct_clone.a.load(Relaxed));
                FLAG.fetch_xor(1, SeqCst);
            }
        }
    });
    spawn(move || {
        loop {
            if FLAG.load(SeqCst) & 2 > 0 {
                atomic_struct.a.store(1,Relaxed);
                print!("{}", atomic_struct.b.load(Relaxed));
                FLAG.fetch_xor(2, SeqCst);
            }
        }
    });

    loop {
        atomic_struct_clone1.a.store(0, Relaxed);
        atomic_struct_clone1.b.store(0, Relaxed);
        FLAG.fetch_xor(3, SeqCst);
        while FLAG.load(SeqCst) != 0 {}
        print!("\n");
        io::stdout().flush().unwrap();
    }
}

